package biz.karms.sinkit.ejb; import biz.karms.sinkit.ejb.cache.annotations.SinkitCache; import biz.karms.sinkit.ejb.cache.annotations.SinkitCacheName; import biz.karms.sinkit.ejb.cache.pojo.BlacklistedRecord; import biz.karms.sinkit.ejb.cache.pojo.CustomList; import biz.karms.sinkit.ejb.cache.pojo.GSBRecord; import biz.karms.sinkit.ejb.cache.pojo.Rule; import biz.karms.sinkit.ejb.cache.pojo.WhitelistedRecord; import biz.karms.sinkit.ejb.cache.pojo.marshallers.CustomListMarshaller; import biz.karms.sinkit.ejb.cache.pojo.marshallers.ImmutablePairMarshaller; import biz.karms.sinkit.ejb.cache.pojo.marshallers.RuleMarshaller; import org.infinispan.client.hotrod.RemoteCache; import org.infinispan.client.hotrod.RemoteCacheManager; import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; import org.infinispan.commons.api.BasicCache; import org.infinispan.commons.api.BasicCacheContainer; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.Configuration; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.global.GlobalConfiguration; import org.infinispan.configuration.global.GlobalConfigurationBuilder; import org.infinispan.eviction.EvictionStrategy; import org.infinispan.eviction.EvictionType; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.protostream.FileDescriptorSource; import org.infinispan.protostream.SerializationContext; import org.infinispan.query.remote.client.ProtobufMetadataManagerConstants; import org.infinispan.util.concurrent.IsolationLevel; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.Destroyed; import javax.enterprise.context.Initialized; import javax.enterprise.event.Observes; import javax.enterprise.inject.Produces; import javax.inject.Inject; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.Serializable; import java.io.StringWriter; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; /** * @author Michal Karm Babacek */ @ApplicationScoped public class MyCacheManagerProvider implements Serializable { private static final long serialVersionUID = 45123839143257496L; private static final long SINKIT_LOCAL_CACHE_SIZE = (System.getenv().containsKey("SINKIT_LOCAL_CACHE_SIZE")) ? Integer.parseInt(System.getenv("SINKIT_LOCAL_CACHE_SIZE")) : 10000; private static final long SINKIT_LOCAL_CACHE_LIFESPAN_MS = (System.getenv().containsKey("SINKIT_LOCAL_CACHE_LIFESPAN_MS")) ? Integer.parseInt(System.getenv("SINKIT_LOCAL_CACHE_LIFESPAN_MS")) : 180000; // This call fails if the property is undefined private static final String SINKIT_HOTROD_HOST = System.getenv("SINKIT_HOTROD_HOST"); private static final int SINKIT_HOTROD_PORT = Integer.parseInt(System.getenv("SINKIT_HOTROD_PORT")); private static final String RULE_PROTOBUF_DEFINITION_RESOURCE = "/sinkitprotobuf/rule.proto"; private static final String CUSTOM_LIST_PROTOBUF_DEFINITION_RESOURCE = "/sinkitprotobuf/customlist.proto"; @Inject private Logger log; private BasicCacheContainer localCacheManager; private RemoteCacheManager cacheManagerForIndexableCaches; private RemoteCacheManager cacheManager; public void init(@Observes @Initialized(ApplicationScoped.class) Object init) throws IOException { log.log(Level.INFO, "Constructing caches..."); if (localCacheManager == null) { final GlobalConfiguration glob = new GlobalConfigurationBuilder() .nonClusteredDefault() .build(); final Configuration loc = new ConfigurationBuilder() .clustering().cacheMode(CacheMode.LOCAL) .locking().isolationLevel(IsolationLevel.READ_UNCOMMITTED) .eviction().strategy(EvictionStrategy.LRU) .type(EvictionType.COUNT).size(SINKIT_LOCAL_CACHE_SIZE) .expiration().lifespan(SINKIT_LOCAL_CACHE_LIFESPAN_MS, TimeUnit.MILLISECONDS) .build(); localCacheManager = new DefaultCacheManager(glob, loc, true); log.info("Local cache manager initialized.\n"); } if (cacheManagerForIndexableCaches == null) { org.infinispan.client.hotrod.configuration.ConfigurationBuilder builder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); builder.addServer() .host(SINKIT_HOTROD_HOST) .port(SINKIT_HOTROD_PORT) .marshaller(new ProtoStreamMarshaller()); cacheManagerForIndexableCaches = new RemoteCacheManager(builder.build()); } if (cacheManager == null) { org.infinispan.client.hotrod.configuration.ConfigurationBuilder builder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); builder.addServer() .host(SINKIT_HOTROD_HOST) .port(SINKIT_HOTROD_PORT); cacheManager = new RemoteCacheManager(builder.build()); } final SerializationContext ctx = ProtoStreamMarshaller.getSerializationContext(cacheManagerForIndexableCaches); ctx.registerProtoFiles(FileDescriptorSource.fromResources(RULE_PROTOBUF_DEFINITION_RESOURCE)); ctx.registerMarshaller(new RuleMarshaller()); ctx.registerMarshaller(new ImmutablePairMarshaller()); ctx.registerProtoFiles(FileDescriptorSource.fromResources(CUSTOM_LIST_PROTOBUF_DEFINITION_RESOURCE)); ctx.registerMarshaller(new CustomListMarshaller()); final RemoteCache<String, String> metadataCache = cacheManagerForIndexableCaches.getCache(ProtobufMetadataManagerConstants.PROTOBUF_METADATA_CACHE_NAME); metadataCache.put(RULE_PROTOBUF_DEFINITION_RESOURCE, readResource(RULE_PROTOBUF_DEFINITION_RESOURCE)); metadataCache.put(CUSTOM_LIST_PROTOBUF_DEFINITION_RESOURCE, readResource(CUSTOM_LIST_PROTOBUF_DEFINITION_RESOURCE)); final String errors = metadataCache.get(ProtobufMetadataManagerConstants.ERRORS_KEY_SUFFIX); if (errors != null) { throw new IllegalStateException("Protobuffer files, either Rule or CustomLists contained errors:\n" + errors); } log.log(Level.INFO, "Managers started."); } @Produces @ApplicationScoped @SinkitCache(SinkitCacheName.cache_manager_indexable) public RemoteCacheManager getCacheManagerForIndexableCaches() { if(cacheManagerForIndexableCaches == null) { throw new IllegalArgumentException("cacheManagerForIndexableCaches must not be null, check init"); } return cacheManagerForIndexableCaches; } @Produces @ApplicationScoped @SinkitCache(SinkitCacheName.infinispan_blacklist) public RemoteCache<String, BlacklistedRecord> getBlacklistCache() { if (cacheManager == null) { throw new IllegalArgumentException("Manager must not be null."); } log.log(Level.INFO, "getBlacklistCache called."); return cacheManager.getCache(SinkitCacheName.infinispan_blacklist.toString()); } @Produces @ApplicationScoped @SinkitCache(SinkitCacheName.infinispan_whitelist) public RemoteCache<String, WhitelistedRecord> getWhitelistCache() { if (cacheManager == null) { throw new IllegalArgumentException("Manager must not be null."); } log.log(Level.INFO, "getWhitelistCache called."); return cacheManager.getCache(SinkitCacheName.infinispan_whitelist.toString()); } @Produces @ApplicationScoped @SinkitCache(SinkitCacheName.infinispan_gsb) public RemoteCache<String, GSBRecord> getGsbCache() { if (cacheManager == null) { throw new IllegalArgumentException("Manager must not be null."); } log.log(Level.INFO, "getGsbCache called."); return cacheManager.getCache(SinkitCacheName.infinispan_gsb.toString()); } @Produces @ApplicationScoped @SinkitCache(SinkitCacheName.custom_lists_local_cache) public BasicCache<String, List<CustomList>> getCustomListLocalCache() { if (localCacheManager == null) { throw new IllegalArgumentException("Manager must not be null."); } log.log(Level.INFO, "getCustomListLocalCache called."); return localCacheManager.getCache(SinkitCacheName.custom_lists_local_cache.toString()); } @Produces @ApplicationScoped @SinkitCache(SinkitCacheName.rules_local_cache) public BasicCache<String, List<Rule>> getRuleLocalCache() { if (localCacheManager == null) { throw new IllegalArgumentException("Manager must not be null."); } log.log(Level.INFO, "getRuleLocalCache called."); return localCacheManager.getCache(SinkitCacheName.rules_local_cache.toString()); } public void destroy(@Observes @Destroyed(ApplicationScoped.class) Object init) { if (localCacheManager != null) { localCacheManager.stop(); } if (cacheManager != null) { cacheManager.stop(); } if (cacheManagerForIndexableCaches != null) { cacheManagerForIndexableCaches.stop(); } } private String readResource(String resourcePath) throws IOException { try (final InputStream is = getClass().getResourceAsStream(resourcePath)) { final Reader r = new InputStreamReader(is, "UTF-8"); final StringWriter w = new StringWriter(); char[] buf = new char[1024]; int len; while ((len = r.read(buf)) != -1) { w.write(buf, 0, len); } return w.toString(); } } }